package com.shanjupay.merchant.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.shanjupay.common.domain.BusinessException;
import com.shanjupay.common.domain.CommonErrorCode;
import com.shanjupay.common.util.PhoneUtil;
import com.shanjupay.merchant.api.MerchantService;
import com.shanjupay.merchant.api.dto.MerchantDTO;
import com.shanjupay.merchant.api.dto.StaffDTO;
import com.shanjupay.merchant.api.dto.StoreDTO;
import com.shanjupay.merchant.convert.MerchantConvert;
import com.shanjupay.merchant.convert.StaffConvert;
import com.shanjupay.merchant.convert.StoreConvert;
import com.shanjupay.merchant.entity.Merchant;
import com.shanjupay.merchant.entity.Staff;
import com.shanjupay.merchant.entity.Store;
import com.shanjupay.merchant.entity.StoreStaff;
import com.shanjupay.merchant.mapper.MerchantMapper;
import com.shanjupay.merchant.mapper.StaffMapper;
import com.shanjupay.merchant.mapper.StoreMapper;
import com.shanjupay.merchant.mapper.StoreStaffMapper;
import com.shanjupay.user.api.TenantService;
import com.shanjupay.user.api.dto.tenant.CreateTenantRequestDTO;
import com.shanjupay.user.api.dto.tenant.TenantDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Transactional
@Service
public class MerchantServiceImpl implements MerchantService {

    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private StoreMapper storeMapper ;

    @Autowired
    private StaffMapper staffMapper ;

    @Autowired
    private StoreStaffMapper storeStaffMapper;

    @Reference
    private TenantService tenantService ;

    /**
     * 查询租户下的商户
     *
     * @param tenantId
     * @return
     */
    @Override
    public MerchantDTO queryMerchantByTenantId(Long tenantId) {
        Merchant merchant = merchantMapper.selectOne(new LambdaQueryWrapper<Merchant>().eq(Merchant::getTenantId, tenantId));
        MerchantDTO merchantDTO = MerchantConvert.INSTANCE.entity2dto(merchant);
        return merchantDTO;
    }

    /**
     * 根据商户id 查询商户信息
     *
     * @param merchantId
     * @return
     * @throws BusinessException
     */
    @Override
    public MerchantDTO queryMerchantById(Long merchantId) throws BusinessException {
        Merchant merchant = merchantMapper.selectById(merchantId);
        MerchantDTO merchantDTO = MerchantConvert.INSTANCE.entity2dto(merchant);
        return merchantDTO;
    }

    @Override
    public MerchantDTO queryById(Long id) {
        Merchant merchant = merchantMapper.selectById(id);
        //MerchantDTO merchantDTO = new MerchantDTO();
        //BeanUtils.copyProperties(merchant,merchantDTO);
        MerchantDTO merchantDTO = MerchantConvert.INSTANCE.entity2dto(merchant);
        return merchantDTO;
    }


    /**
     *  注册商户服务接口， 接收账号， 手机号，密码， 为了可扩展性使用 DTO 接收数据
     *
     *      调用SaaS 接口： 新增租户，用户，绑定租户和用户的关系，初始化权限
     *
     * @param merchantDTO  商户注册信息
     * @return  注册成功的商户信息
     * @throws BusinessException
     */
    @Override
    public MerchantDTO createMerchant(MerchantDTO merchantDTO) throws BusinessException {

        // 校验参数的合法性
        if(merchantDTO == null) {
            throw new BusinessException(CommonErrorCode.E_100108);
        }

        // 手机号校验
        if(StringUtils.isBlank(merchantDTO.getMobile())){
            // 手机号为空
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        // 手机号格式校验
        if(!PhoneUtil.isMatches(merchantDTO.getMobile())){
            throw new BusinessException(CommonErrorCode.E_100109);
        }

        // 手机号唯一性校验
        // 根据手机号查询商户表， 如果存在记录则说明手机号已经存在。
        Integer count = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>().eq(Merchant::getMobile, merchantDTO.getMobile()));
        if(count>0){
            // 手机号已经存在
            throw new BusinessException(CommonErrorCode.E_100113);
        }

        // 调用SaaS 接口
        CreateTenantRequestDTO accountRequestDTO = new CreateTenantRequestDTO();
        // 手机号
        accountRequestDTO.setMobile(merchantDTO.getMobile());
        // 账号
        accountRequestDTO.setUsername(merchantDTO.getUsername());
        // 密码
        accountRequestDTO.setPassword(merchantDTO.getPassword());
        // 租户类型
        accountRequestDTO.setTenantTypeCode("shanju-merchant");
        // 默认套餐, 根据套餐进行分配权限
        accountRequestDTO.setBundleCode("shanju-merchant");
        // 租户名称
        accountRequestDTO.setName(merchantDTO.getUsername());

        // 如果租户在Sass 已经存在，Saas直接 返回此租户的信息，否则进行添加操作
        TenantDTO tenantAndAccount = tenantService.createTenantAndAccount(accountRequestDTO);
        // 获取租户的id
        if(tenantAndAccount == null || tenantAndAccount.getId() == null ){
            throw new BusinessException(CommonErrorCode.E_200012);
        }
        Long tenantId = tenantAndAccount.getId();

        // 租户id 在商户表唯一
        // 根据租户id从商户表查询，如果存在记录则不允许添加商户
        Integer selectCount = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>().eq(Merchant::getTenantId, tenantAndAccount));
        if(selectCount>0){
            throw new BusinessException(CommonErrorCode.E_200017);
        }

        //Merchant merchant = new Merchant();

        // 使用MapStruct 进行对象转换
        Merchant merchant = MerchantConvert.INSTANCE.dto2entity(merchantDTO);

        //merchant.setMobile(merchantDTO.getMobile());
        // 舍河状态为0 未进行资质申请
        merchant.setAuditStatus("0");
        // 设置所对应的租户的Id
        merchant.setTenantId(tenantId);
        // 调用Mapper 向数据库中插入记录
        merchantMapper.insert(merchant);

        // 新增门店
        StoreDTO store = new StoreDTO();
        store.setStoreName("根门店");
        store.setMerchantId(merchant.getId());
        store.setStoreStatus(true);
        StoreDTO storeDTO = createStore(store);

        // 新增员工
        StaffDTO staffDTO = new StaffDTO();
        // 手机号
        staffDTO.setMobile(merchantDTO.getMobile());
        // 账号：
        staffDTO.setUsername(merchantDTO.getUsername());
        // 员工所属门店的id
        staffDTO.setStoreId(storeDTO.getId());
        // 商户id
        staffDTO.setMerchantId(merchant.getId());
        // 员工状态  启用
        staffDTO.setStaffStatus(true);

        StaffDTO staff = createStaff(staffDTO);
        // 为门店设置管理员
        bindStaffToStore(storeDTO.getId(),staff.getId());

        // 将dto中写入新增商户的id
        //merchantDTO.setId(merchant.getId());

        merchantDTO = MerchantConvert.INSTANCE.entity2dto(merchant);

        return merchantDTO;
    }

    /**
     * 资质申请
     *
     * @param merchantId  商户id
     * @param merchantDTO 资质申请信息
     * @throws BusinessException
     */
    @Override
    public void applyMerchant(Long merchantId, MerchantDTO merchantDTO) throws BusinessException {
        // 参数校验
        if(merchantId == null || merchantDTO == null){
            throw new BusinessException(CommonErrorCode.E_300009);
        }
        // 校验merchantId 的合法性， 查询商户表，如果查询不到记录， 认为非法
        Merchant merchant = merchantMapper.selectById(merchantId);
        if(merchant == null) {
            throw new BusinessException(CommonErrorCode.E_200002);
        }
        // 将dto 转换成 entity
        Merchant entity = MerchantConvert.INSTANCE.dto2entity(merchantDTO);

        // 将必要的参数设置到entity
        entity.setId(merchantId);
        // 因为资质申请的时候手机号不让改，所以要设置进去 数据库中原来的手机号
        entity.setMobile(merchant.getMobile());
        // 设置 审核的状态  1-已申请待审核
        entity.setAuditStatus("1");
        entity.setTenantId(merchant.getTenantId());

        // 调用Mapper 更新商户表记录
        int updateResult = merchantMapper.updateById(entity);

        log.info("商户号为：{} 更新结果: {}",merchantId,updateResult);
    }

    /**
     * 新增门店
     *
     * @param storeDTO 门店信息
     * @return 新增成功的门店信息
     * @throws BusinessException
     */
    @Override
    public StoreDTO createStore(StoreDTO storeDTO) throws BusinessException {

        Store entity = StoreConvert.INSTANCE.dto2entity(storeDTO);
        log.info("新增门店信息：{}", JSON.toJSONString(entity));
        // 新增门店
        int insert = storeMapper.insert(entity);
        log.info("新增门店的结果："+ insert);
        StoreDTO dto = StoreConvert.INSTANCE.entity2dto(entity);
        return dto;
    }

    /**
     * 新增员工
     *
     * @param staffDTO
     * @return
     * @throws BusinessException
     */
    @Override
    public StaffDTO createStaff(StaffDTO staffDTO) throws BusinessException {

        // 参数的合法性校验
        if(staffDTO == null   || StringUtils.isBlank(staffDTO.getUsername())
            || staffDTO.getStoreId() == null ){
            throw new BusinessException(CommonErrorCode.E_300009);
        }
        // 校验手机号
        if(StringUtils.isBlank( staffDTO.getMobile())){
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        // 在同一个商户下员工的 手机号唯一(根据商户id和手机号校验唯一性）
        if(isExistStaffByMobile(staffDTO.getMobile(),staffDTO.getMerchantId())){
            throw new BusinessException(CommonErrorCode.E_100113);
        }
        // 在同一个商户下员工的账号唯一，（根据商户id和账号校验唯一性）
        if(isExistStaffByUserName(staffDTO.getUsername(),staffDTO.getMerchantId())){
            throw new BusinessException(CommonErrorCode.E_100114);
        }

        Staff staff = StaffConvert.INSTANCE.dto2entity(staffDTO);

        log.info("商户下新增员工：{}",JSON.toJSONString(staff));

        int insert = staffMapper.insert(staff);

        log.info("商户下新增员工的返回结果："+insert);

        StaffDTO dto = StaffConvert.INSTANCE.entity2dto(staff);

        return dto;
    }

    /**
     * 为门店设置管理员（将员工设置为门店管理员）
     *
     * @param storeId
     * @param staffId
     * @throws BusinessException
     */
    @Override
    public void bindStaffToStore(Long storeId, Long staffId) throws BusinessException {

        //
        StoreStaff storeStaff = new StoreStaff();
        storeStaff.setStaffId(staffId);
        storeStaff.setStoreId(storeId);

        int insert = storeStaffMapper.insert(storeStaff);

        log.info("新增门店管理员的结果：{}",insert);

    }

    /**
     *  根据手机号判断员工是否已在指定商户存在
     *
     * @param mobile
     * @param merchantId
     * @return
     */
    private boolean isExistStaffByMobile(String mobile,Long merchantId) {
        LambdaQueryWrapper<Staff> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        lambdaQueryWrapper.eq(Staff::getMobile,mobile)
                .eq(Staff::getMerchantId,merchantId);

        int result = staffMapper.selectCount(lambdaQueryWrapper);
        return result > 0 ;
    }

    /**
     *  根据账号判断员工是否已在指定商户存在。
     *
     * @param userName
     * @param merchantId
     * @return
     */
    private boolean isExistStaffByUserName(String userName,Long merchantId) {
        LambdaQueryWrapper<Staff> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Staff::getUsername,userName )
                .eq(Staff::getMerchantId,merchantId);

        int result = staffMapper.selectCount(lambdaQueryWrapper);
        return result > 0 ;
    }



}
